/**
 * @file RssReader.cpp
 *
 * Klasa czytnika RSS - implementacja.
 *
 * @author Zbigniew Siciarz
 * @date 2009
 * @version 2.0.0
 * @since 2.0.0
 */

#include "RssReader.h"

#include <QDateTime>
#include <QtNetwork>
#include <QtXml>


/**
 * Konstruktor - inicjalizuje czytnik RSS.
 *
 * @param parent obiekt rodzica
 */
RssReader::RssReader(QObject* parent):
    QObject(parent), m_mgr(0)
{
}

/**
 * Destruktor - niszczy obiekt czytnika.
 */
RssReader::~RssReader()
{
}

/**
 * Pobiera XML z danego serwera.
 *
 * Rozpoczyna asynchroniczne połączenie z serwerem. Po odebraniu odpowiedzi
 * wywoła slot readFinished().
 *
 * @param url obiekt adresu URL (wygodniej tak niż jako string)
 */
void RssReader::downloadFeed(const QUrl& url)
{
    if (m_mgr)
    {
        QNetworkReply* reply = m_mgr->get(QNetworkRequest(url));
        connect(reply, SIGNAL(finished()), this, SLOT(readFinished()));
    }
}

/**
 * Zwraca ciąg znaków nadający się do wstawienia do labela/textedita.
 *
 * @return RSS przeparsowany i sformatowany tak jak chcemy
 */
QString RssReader::getParsedFeed() const
{
    return formattedFeed;
}

/**
 * Obsługuje zakończenie odczytu RSS-a z serwera.
 *
 * Pobiera zawartość odpowiedzi, a następnie parsuje i formatuje odebrany XML.
 */
void RssReader::readFinished()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
    if (reply)
    {
        if (QNetworkReply::NoError == reply->error())
        {
            parseReply(reply);
        }
    }

    emit parsingFinished();
}

/**
 * Przetwarza odpowiedź za pomocą parsera DOM.
 */
void RssReader::parseReply(QNetworkReply* reply)
{
    QString errorStr;
    int errorLine, errorColumn;
    QDomDocument doc;

    if (!doc.setContent(reply, false, &errorStr, &errorLine,
                        &errorColumn))
    {
        formattedFeed = tr("Błąd składni w linii %1, kolumnie %2: %3").
                arg(errorLine).arg(errorColumn).arg(errorStr);
        return;
    }

    QDomElement root = doc.documentElement();
    if (root.tagName() != "rss")
    {
        formattedFeed = tr("To nie jest plik RSS! (Element nadrzędny: %1").
                arg(root.tagName());
        return;
    }

    QDomNodeList list = root.elementsByTagName("item");
    for (unsigned int i = 0, length = list.length(); i < length; ++i)
    {
        QDomNode node = list.at(i);
        if (node.isElement() && node.toElement().tagName() == "item")
        {
            parseItem(node.toElement());
        }
    }
}

/**
 * Przetwarza pojedynczy tag <item>...<item>.
 *
 * @param element obiekt elementu DOM zawierający tag <item>
 */
void RssReader::parseItem(const QDomElement& element)
{
    QString title = element.elementsByTagName("title").at(0).toElement().text();
    QString description = element.elementsByTagName("description").at(0).toElement().text();
    QString link = element.elementsByTagName("link").at(0).toElement().text();
    QString date = element.elementsByTagName("pubDate").at(0).toElement().text();

    QString item = m_template;
    item.replace("%title%", title).replace("%description%", description).
            replace("%link%", link).replace("%date%", date);
    formattedFeed += item;
}
